/*
 * Copyright 2014 OGIS-RI All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jp.co.ogis_ri.optaplanner.vehiclerouting;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import jp.co.ogis_ri.optaplanner.vehiclerouting.domain.Break;
import jp.co.ogis_ri.optaplanner.vehiclerouting.domain.Cargo;
import jp.co.ogis_ri.optaplanner.vehiclerouting.domain.Depot;
import jp.co.ogis_ri.optaplanner.vehiclerouting.domain.Location;
import jp.co.ogis_ri.optaplanner.vehiclerouting.domain.SolutionParameter;
import jp.co.ogis_ri.optaplanner.vehiclerouting.domain.Vehicle;
import jp.co.ogis_ri.optaplanner.vehiclerouting.domain.VehicleRoutingSolution;
import jp.co.ogis_ri.optaplanner.vehiclerouting.domain.core.ChainedTimeWindowedStep;

import org.apache.commons.math3.random.MersenneTwister;
import org.apache.commons.math3.random.RandomAdaptor;

public class va {

	public VehicleRoutingSolution createSolution() {

		long id = 0;

		//
		Location locationDummy = new Location();
		locationDummy.setId(id++);
		locationDummy.setLatitude(0);
		locationDummy.setLongitude(0);
		locationDummy.setName("Dummy");

		Depot depotDummy = new Depot();
		depotDummy.setId(id++);
		depotDummy.setLocation(locationDummy);

		Vehicle vehicleDummy = new Vehicle();
		vehicleDummy.setId(id++);
		vehicleDummy.setDummy(true);
		vehicleDummy.setDepot(depotDummy);

		// 車両A
		Location locationA = new Location();
		locationA.setId(id++);
		locationA.setLatitude(0.5);
		locationA.setLongitude(0.5);
		locationA.setName("BaseA");

		Depot depotA = new Depot();
		depotA.setId(id++);
		depotA.setLocation(locationA);

		Vehicle vehicleA = new Vehicle();
		vehicleA.setId(id++);
		vehicleA.setDepot(depotA);
		vehicleA.setCapacity(200);
		vehicleA.setReadyTime(0);
		vehicleA.setDueTime(10000);

		// 車両B
		Location locationB = new Location();
		locationB.setId(id++);
		locationB.setLatitude(1.5);
		locationB.setLongitude(1.5);
		locationB.setName("BaseB");

		Depot depotB = new Depot();
		depotB.setId(id++);
		depotB.setLocation(locationB);

		Vehicle vehicleB = new Vehicle();
		vehicleB.setId(id++);
		vehicleB.setDepot(depotB);
		vehicleB.setCapacity(200);
		vehicleB.setReadyTime(0);
		vehicleB.setDueTime(10000);

		// 車両C
		Location locationC = new Location();
		locationC.setId(id++);
		locationC.setLatitude(1.5);
		locationC.setLongitude(0.5);
		locationC.setName("BaseC");

		Depot depotC = new Depot();
		depotC.setId(id++);
		depotC.setLocation(locationC);

		Vehicle vehicleC = new Vehicle();
		vehicleC.setId(id++);
		vehicleC.setDepot(depotC);
		vehicleC.setCapacity(200);
		vehicleC.setReadyTime(0);
		vehicleC.setDueTime(10000);

		// 車両D
		Location locationD = new Location();
		locationD.setId(id++);
		locationD.setLatitude(0.5);
		locationD.setLongitude(1.5);
		locationD.setName("BaseD");

		Depot depotD = new Depot();
		depotD.setId(id++);
		depotD.setLocation(locationD);

		Vehicle vehicleD = new Vehicle();
		vehicleD.setId(id++);
		vehicleD.setDepot(depotD);
		vehicleD.setCapacity(200);
		vehicleD.setReadyTime(0);
		vehicleD.setDueTime(10000);

		//
		List<ChainedTimeWindowedStep> chainedTimeWindowedStepList = new ArrayList<ChainedTimeWindowedStep>();

		List<Location> locationList = new ArrayList<Location>();
		locationList.add(locationDummy);
		locationList.add(locationA);
		locationList.add(locationB);
		locationList.add(locationC);
		locationList.add(locationD);

		// デモなので、シードは固定しておきます
		Random random = RandomAdaptor.createAdaptor(new MersenneTwister(0));

		// 荷物
		for (int i = 0; i < 100; i++) {

			Location location = new Location();
			location.setId(id++);
			location.setLatitude(random.nextDouble() * 2d);
			location.setLongitude(random.nextDouble() * 2d);
			location.setName("Location" + id);

			locationList.add(location);

			Cargo cargo = new Cargo();
			cargo.setId(id);
			cargo.setLocation(location);
			cargo.setSize(3);

			if (i <= 33) {
				cargo.setReadyTime(0);
				cargo.setDueTime(5000);
			} else if (34 <= i && i <= 68) {
				cargo.setReadyTime(2500);
				cargo.setDueTime(7500);
			} else {
				cargo.setReadyTime(5000);
				cargo.setDueTime(10000);
			}

			cargo.setServiceDuration(100);

			chainedTimeWindowedStepList.add(cargo);
		}

		// 休憩
		for (int i = 0; i < 4; i++) {
			Break break1 = new Break();
			break1.setId(id++);
			break1.setReadyTime(2500);
			break1.setDueTime(7500);
			break1.setBreakTime(500);

			chainedTimeWindowedStepList.add(break1);
		}

		List<Depot> depotList = new ArrayList<Depot>();
		depotList.add(depotDummy);
		depotList.add(depotA);
		depotList.add(depotB);
		depotList.add(depotC);
		depotList.add(depotD);

		List<Vehicle> vehicleList = new ArrayList<Vehicle>();
		vehicleList.add(vehicleDummy);
		vehicleList.add(vehicleA);
		vehicleList.add(vehicleB);
		vehicleList.add(vehicleC);
		vehicleList.add(vehicleD);

		SolutionParameter solutionParameter = new SolutionParameter();
		solutionParameter.setCountAverage(300F / 4F);

		VehicleRoutingSolution solution = new VehicleRoutingSolution();
		solution.setId(id++);
		solution.setName("VehicleRoutingSolution");
		solution.setCargoList(chainedTimeWindowedStepList);
		solution.setDepotList(depotList);
		solution.setLocationList(locationList);
		solution.setVehicleList(vehicleList);
		solution.setSolutionParameter(solutionParameter);

		return solution;
	}
}
